import VisFragment, { Pair, PairWithDetector } from "@/types/VisFragment";
import React, { Dispatch, SetStateAction, useState } from "react";
import styles from "@/styles/ResultDisplay.module.sass";
import { Button } from "antd";
import DiffInfoDisplay from "./DiffInfoDisplay";
import TreeBar, { PathAndDetector } from "./TreeBar";
import VisCUNode from "@/types/VisCUNode";
import NodeComponentDisplay from "./NodeComponentDisplay/NodeComponentDisplay";
import { NodeDataType } from "@/types/TreeBarTypes";
import { RefactoringType } from "@/types/RefactoringType";

const ResultDisplay = (props: {
  data: VisFragment;
  setData: Dispatch<
    SetStateAction<{ ifSuccessful: boolean; fragment: VisFragment }>
  >;
}) => {
  // clear the data displaying to get back to the input form
  const clearData = () => {
    props.setData({ ifSuccessful: false, fragment: {} as VisFragment });
  };

  const { cuPairsWithDetector, ...rest } = props.data;
  // change pairWithDetectors to pathAndDetector for the TreeBars
  const getTreeData: (
    aOrb: keyof Pair<VisCUNode, VisCUNode>
  ) => PathAndDetector[] = (aOrb) =>
    cuPairsWithDetector
      .filter((eachPWD) => eachPWD.pair[aOrb])
      .map((eachPWD) => {
        if (!!eachPWD.detector) {
          return {
            path: eachPWD.pair[aOrb]?.pathString.replaceAll("\\", "/"), // path unified
            detector: eachPWD.detector,
          };
        } else {
          return {
            path: eachPWD.pair[aOrb]?.pathString.replaceAll("\\", "/"),
          };
        }
      }) as PathAndDetector[];

  // states
  const [baseTreeData] = useState<PathAndDetector[]>(getTreeData("a"));
  const [modifiedTreeData] = useState<PathAndDetector[]>(getTreeData("b"));
  const [refactorType2Display, setRefactorType2Display] = useState<
    RefactoringType[] | undefined
  >(undefined);
  const [displayInfo, setDisplayInfo] = useState<{
    leftCu: VisCUNode | undefined;
    rightCu: VisCUNode | undefined;
    leftRanges: Range[] | undefined;
    rightRanges: Range[] | undefined;
  }>({
    leftCu: undefined,
    rightCu: undefined,
    leftRanges: undefined,
    rightRanges: undefined,
  });
  const [selectedKeyForTrees, setSelectedKeyForTrees] = useState<{
    leftKey: string[]; // TreeBar component from antd need an array
    rightKey: string[];
  }>({ leftKey: [], rightKey: [] });

  // select event handler from the tree bars
  const selectHandler = (
    data: NodeDataType | undefined,
    key: React.Key | undefined
  ) => {
    if (!data || !key) {
      // set display empty
      setDisplayInfo({
        leftCu: undefined,
        rightCu: undefined,
        leftRanges: undefined,
        rightRanges: undefined,
      });
      setSelectedKeyForTrees({
        leftKey: [],
        rightKey: [],
      });
      setRefactorType2Display(undefined);
      return;
    }

    // display cu
    const { isBase, pathString, refactorType } = data;
    const aOrb = isBase ? "a" : "b";
    const cuWDPair: PairWithDetector = props.data.cuPairsWithDetector.filter(
      (pairWD) =>
        !!pairWD.pair[aOrb] &&
        pairWD.pair[aOrb]?.pathString.replaceAll("\\", "/") === pathString
    )[0]; //assert there will be one and only one
    setRefactorType2Display(refactorType);
    setDisplayInfo({
      leftCu: cuWDPair.pair.a,
      rightCu: cuWDPair.pair.b,
      leftRanges: data.baseRanges, // undefined for FileNode
      rightRanges: data.modifiedRanges,
    });
    // get left/right filepath and construct 2 keys for 2 treesd
    const other = isBase ? "b" : "a";
    const splittedKey = key.toString().split(">");
    const s = cuWDPair.pair[other]?.pathString;
    let switchedKey = undefined;
    if (!!s) {
      splittedKey[0] = s;
      switchedKey = splittedKey.join(">").replaceAll("\\", "/");
    }
    const leftKey = isBase ? key : switchedKey;
    const rightKey = isBase ? switchedKey : key;
    // sync selection
    setSelectedKeyForTrees({
      // tree key needed to be an array but actually we only allow one selected at each time
      leftKey: leftKey ? [leftKey as string] : [],
      rightKey: rightKey ? [rightKey as string] : [],
    });
  };

  const { leftCu, rightCu, leftRanges, rightRanges } = displayInfo;
  return (
    <>
      <div className={styles.header}>
        <Button
          onClick={clearData}
          size="large"
          style={{ height: "100%" }}
          type="primary"
        >
          返回
        </Button>
      </div>
      <div className={styles.main}>
        <TreeBar
          selectHandler={selectHandler}
          selectedKeys={selectedKeyForTrees.leftKey}
          pathAndDetector={baseTreeData}
          isBase
          position="left"
        />

        <section className={styles.displayContainer}>
          {/* 目前title先写死 */}
          <DiffInfoDisplay
            title="变更信息"
            data={rest}
            refactorType={refactorType2Display}
          />

          <NodeComponentDisplay
            leftCu={leftCu}
            leftRanges={leftRanges}
            rightCu={rightCu}
            rightRanges={rightRanges}
          />
        </section>

        <TreeBar
          selectHandler={selectHandler}
          selectedKeys={selectedKeyForTrees.rightKey}
          pathAndDetector={modifiedTreeData}
          isBase={false}
          position="right"
        />
      </div>
    </>
  );
};

export default ResultDisplay;
